home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (C) 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- #include <stdio.h>
- #include <math.h>
- #include <malloc.h>
-
- #include "vroom.h"
- #include "track.h"
- #include "car.h"
- #include "body.h"
-
- #define FOLLOW_OK 0
- #define FOLLOW_NEXT 1
- #define FOLLOW_WIPE_OUT_LEFT 2
- #define FOLLOW_WIPE_OUT_RIGHT 3
-
- #define BEGINNING 0x00
- #define ENDING 0x01
- #define LEFT_SIDE 0x00
- #define RIGHT_SIDE 0x02
-
- #define CX_PART 0x04
- #define CY_PART 0x08
- #define DT_PART 0x0c
- #define R_PART 0x10
-
- #define DXDS(t) ( (t)->c[0] )
- #define DYDS(t) ( (t)->c[1] )
- #define DXDL(t) ( (t)->c[2] )
- #define DYDL(t) ( (t)->c[3] )
- #define CX_LEFT_BEG(t) ( (t)->c[4] )
- #define CX_LEFT_END(t) ( (t)->c[5] )
- #define CX_RIGHT_BEG(t) ( (t)->c[6] )
- #define CX_RIGHT_END(t) ( (t)->c[7] )
- #define CY_LEFT_BEG(t) ( (t)->c[8] )
- #define CY_LEFT_END(t) ( (t)->c[9] )
- #define CY_RIGHT_BEG(t) ( (t)->c[10] )
- #define CY_RIGHT_END(t) ( (t)->c[11] )
- #define DTHETA_DS_LEFT_BEG(t) ( (t)->c[12] )
- #define DTHETA_DS_LEFT_END(t) ( (t)->c[13] )
- #define DTHETA_DS_RIGHT_BEG(t) ( (t)->c[14] )
- #define DTHETA_DS_RIGHT_END(t) ( (t)->c[15] )
- #define R_LEFT_BEG(t) ( (t)->c[16] )
- #define R_LEFT_END(t) ( (t)->c[17] )
- #define R_RIGHT_BEG(t) ( (t)->c[18] )
- #define R_RIGHT_END(t) ( (t)->c[19] )
-
- /* BEGIN PROTOTYPES -S merge.c */
- static void addedMergeInTrack( Track *track ) ;
- static void addedMergeOutTrack( Track *track ) ;
- static void addToMergeTrack( Track *old, Track *new ) ;
- static void drawMergeOutline( Track *track, int side ) ;
- static void drawMergeTrack( Track *track, int lod ) ;
- static void drawMergeTrackMarkers( Track *track, int lod ) ;
- static void enterMergeOutTrack( Track *track, Car *car ) ;
- static int followMergeTrack( Track *track, Car *car, float dTime ) ;
- static void followTheMergeTrack( Track *track, Car *car, float dTime ) ;
- static void freeMergeTrack( Track *track ) ;
- static void getLocation( Track *track, float s, float lane, float *x,
- float *y, float *theta, float *radius ) ;
- static float getTrackLength( Track *track, float lane ) ;
- static float mergeLaneWidth( Track *track, float s, float lane1,
- float lane2 ) ;
- static float topSpeedMergeTrack( Track *track, float s, float l ) ;
- /* END PROTOTYPES -S merge.c */
-
-
-
- /*------------------------------------------------------------------------------
- * Follow a merge piece of track.
- *----------------------------------------------------------------------------*/
- static int
- followMergeTrack(
- Track *track,
- Car *car,
- float dTime
- )
- {
- int doNext = 0 ;
- int laneLo ;
- int laneHi ;
- float length ;
- float radius ;
- float theta ;
- float c ;
- float s ;
- float eTime ;
- float newS ;
- float partialLane ;
- Track *nextTrack ;
-
- if( car->lane < 1.0f || car->lane > (float)track->lanes )
- {
- if( car->lane < 1.0f )
- {
- return( FOLLOW_WIPE_OUT_LEFT ) ;
- }
- else
- {
- return( FOLLOW_WIPE_OUT_RIGHT ) ;
- }
- }
- else
- {
- laneLo = (int)floorf( car->lane ) ;
- laneHi = (int)ceilf( car->lane ) ;
- partialLane = car->lane - laneLo ;
- length = partialLane * track->length[laneLo-1] +
- ( 1.0f - partialLane ) * track->length[laneHi-1] ;
- newS = car->s + car->speed * dTime / length ;
- if( newS >= 1.0f )
- {
- eTime = ( 1.0f - car->s ) * length /
- car->speed ;
- dTime -= eTime ;
- car->s = 0.0f ;
- car->track = track->nextTrack ;
- incrementLap( car, dTime ) ;
- if( track->type == MERGE_IN_TRACK )
- {
- if( car->lane < 2.0f )
- {
- car->lane = 1.0f ;
- }
- else if( car->lane > track->lanes - 1 )
- {
- car->lane = track->lanes - 2 ;
- }
- else
- {
- car->lane -= 1.0f ;
- }
- laneLo = (int)floorf( car->lane ) ;
- laneHi = (int)ceilf( car->lane ) ;
- partialLane = car->lane - laneLo ;
- }
- car->track->enter( car->track, car ) ;
- doNext = 1 ;
- }
- else
- {
- eTime = dTime ;
- car->s = newS ;
- }
- if( car->status & CHANGE_LANE_RIGHT )
- {
- partialLane += eTime * LANE_CHANGE_SPEED ;
- if( partialLane > 1.0f )
- {
- car->status &= ~CHANGE_LANE_RIGHT ;
- car->lane = laneLo + 1.0f ;
- }
- else
- {
- car->lane = laneLo + partialLane ;
- }
- }
- else if( car->status & CHANGE_LANE_LEFT )
- {
- partialLane = laneHi - car->lane ;
- partialLane += eTime * LANE_CHANGE_SPEED ;
- if( partialLane > 1.0f )
- {
- car->status &= ~CHANGE_LANE_LEFT ;
- car->lane = laneHi - 1.0f ;
- }
- else
- {
- car->lane = laneHi - partialLane ;
- }
- }
- if( doNext )
- {
- car->track->follow( car->track, car, dTime ) ;
- return( FOLLOW_NEXT ) ;
- }
- }
-
- return( FOLLOW_OK ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Follow a merge piece of track.
- *----------------------------------------------------------------------------*/
- static void
- followTheMergeTrack(
- Track *track,
- Car *car,
- float dTime
- )
- {
- float wvx ;
- float wvy ;
- float radius ;
- float theta ;
- float c ;
- float s ;
- float force ;
-
- switch( followMergeTrack( track, car, dTime ) )
- {
- case FOLLOW_OK :
- getLocation( track, car->s, car->lane, &car->x, &car->y,
- &theta, &radius ) ;
- car->theta = theta ;
- force = centrifugalForce( car->speed, radius ) ;
- if( force >= 1.0f )
- {
- wvx = cosf( theta + (float)M_PI * 0.3333f ) ;
- wvy = sinf( theta + (float)M_PI * 0.3333f ) ;
- wipeOutCar( car, wvx, wvy, 1, WIPE_OUT_SPEED ) ;
- }
- else if( force > 0.0f )
- {
- startSkid( car, force, dTime ) ;
- }
- else
- {
- if( car->status & CAR_SKID )
- {
- stopSkid( car ) ;
- }
- }
- break ;
-
- case FOLLOW_NEXT :
- break ;
-
- case FOLLOW_WIPE_OUT_LEFT :
- theta = car->theta ;
- wvx = cosf( theta + (float)M_PI * 0.8333f ) ;
- wvy = sinf( theta + (float)M_PI * 0.8333f ) ;
- wipeOutCar( car, wvx, wvy, -1, WIPE_OUT_OFF_ROAD ) ;
- break ;
-
- case FOLLOW_WIPE_OUT_RIGHT :
- theta = car->theta ;
- wvx = cosf( theta + (float)M_PI * 0.3333f ) ;
- wvy = sinf( theta + (float)M_PI * 0.3333f ) ;
- wipeOutCar( car, wvx, wvy, 1, WIPE_OUT_OFF_ROAD ) ;
- break ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Initialize after adding track.
- *----------------------------------------------------------------------------*/
- static void
- addedMergeInTrack(
- Track *track
- )
- {
- int i ;
- float radius ;
- float ct ;
- float st ;
- float len ;
- float r ;
- float a ;
- float dt ;
-
- len = track->length[0] ;
-
- ct = cosf( track->theta ) ;
- st = sinf( track->theta ) ;
- DXDS( track ) = -st * len ;
- DYDS( track ) = ct * len ;
- DXDL( track ) = ct * LANE_WIDTH ;
- DYDL( track ) = st * LANE_WIDTH ;
-
- a = len * len + LANE_WIDTH * LANE_WIDTH ;
- r = a / ( 4.0f * LANE_WIDTH ) ;
- dt = 2.0f * asinf( 2.0f * LANE_WIDTH * len / a ) ;
-
- a = r - ( track->midLane - 1.0f ) * LANE_WIDTH ;
-
- CX_LEFT_BEG( track ) = track->x + a * ct ;
- CY_LEFT_BEG( track ) = track->y + a * st ;
- DTHETA_DS_LEFT_BEG( track ) = -dt ;
- R_LEFT_BEG( track ) = -r ;
-
- CX_RIGHT_BEG( track ) = track->x - a * ct ;
- CY_RIGHT_BEG( track ) = track->y - a * st ;
- DTHETA_DS_RIGHT_BEG( track ) = dt ;
- R_RIGHT_BEG( track ) = r ;
-
- a = r + ( track->midLane - 2.0f ) * LANE_WIDTH ;
-
- CX_LEFT_END( track ) = track->x - st * len - a * ct ;
- CY_LEFT_END( track ) = track->y + ct * len - a * st ;
- DTHETA_DS_LEFT_END( track ) = dt ;
- R_LEFT_END( track ) = r ;
-
- CX_RIGHT_END( track ) = track->x - st * len + a * ct ;
- CY_RIGHT_END( track ) = track->y + ct * len + a * st ;
- DTHETA_DS_RIGHT_END( track ) = -dt ;
- R_RIGHT_END( track ) = -r ;
-
- track->length[0] = 1.0f * r * dt ;
- track->length[track->lanes-1] = 1.0f * r * dt ;
-
- for( i = 0 ; i < MAX_LOD ; i++ )
- {
- glNewList( track->drawList+i, GL_COMPILE ) ;
- drawMergeTrack( track, i ) ;
- glEndList() ;
- glNewList( track->drawMarkerList+i, GL_COMPILE ) ;
- drawMergeTrackMarkers( track, i ) ;
- glEndList() ;
- }
-
- /*
- * Compute the cull radius from the center point.
- */
- radius = 0.5f * track->lanes * LANE_WIDTH + SIDE_MARKER_WIDTH ;
- radius = 0.5f * sqrtf( track->length[1] * track->length[1] +
- radius * radius ) ;
-
- track->center[0] = track->x + 0.5f * DXDS( track ) ;
- track->center[1] = track->y + 0.5f * DYDS( track ) ;
- track->center[2] = 0.0f ;
-
- track->cullDetail = trackDetail( radius ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Initialize after adding track.
- *----------------------------------------------------------------------------*/
- static void
- addedMergeOutTrack(
- Track *track
- )
- {
- int i ;
- float radius ;
- float ct ;
- float st ;
- float len ;
- float r ;
- float a ;
- float dt ;
-
- len = track->length[0] ;
-
- ct = cosf( track->theta ) ;
- st = sinf( track->theta ) ;
- DXDS( track ) = -st * len ;
- DYDS( track ) = ct * len ;
- DXDL( track ) = ct * LANE_WIDTH ;
- DYDL( track ) = st * LANE_WIDTH ;
-
- a = len * len + LANE_WIDTH * LANE_WIDTH ;
- r = a / ( 4.0f * LANE_WIDTH ) ;
- dt = 2.0f * asinf( 2.0f * LANE_WIDTH * len / a ) ;
-
- a = r + ( track->midLane - 2.0f ) * LANE_WIDTH ;
-
- CX_LEFT_BEG( track ) = track->x - a * ct ;
- CY_LEFT_BEG( track ) = track->y - a * st ;
- DTHETA_DS_LEFT_BEG( track ) = dt ;
- R_LEFT_BEG( track ) = r ;
-
- CX_RIGHT_BEG( track ) = track->x + a * ct ;
- CY_RIGHT_BEG( track ) = track->y + a * st ;
- DTHETA_DS_RIGHT_BEG( track ) = -dt ;
- R_RIGHT_BEG( track ) = -r ;
-
- a = r - ( track->midLane - 1.0f ) * LANE_WIDTH ;
-
- CX_LEFT_END( track ) = track->x - st * len + a * ct ;
- CY_LEFT_END( track ) = track->y + ct * len + a * st ;
- DTHETA_DS_LEFT_END( track ) = -dt ;
- R_LEFT_END( track ) = -r ;
-
- CX_RIGHT_END( track ) = track->x - st * len - a * ct ;
- CY_RIGHT_END( track ) = track->y + ct * len - a * st ;
- DTHETA_DS_RIGHT_END( track ) = dt ;
- R_RIGHT_END( track ) = r ;
-
- track->length[0] = r * dt ;
- track->length[track->lanes-1] = r * dt ;
-
- for( i = 0 ; i < MAX_LOD ; i++ )
- {
- glNewList( track->drawList+i, GL_COMPILE ) ;
- drawMergeTrack( track, i ) ;
- glEndList() ;
- glNewList( track->drawMarkerList+i, GL_COMPILE ) ;
- drawMergeTrackMarkers( track, i ) ;
- glEndList() ;
- }
-
- /*
- * Compute the cull radius from the center point.
- */
- radius = 0.5f * track->lanes * LANE_WIDTH + SIDE_MARKER_WIDTH ;
- radius = 0.5f * sqrtf( track->length[0] * track->length[0] +
- radius * radius ) ;
-
- track->center[0] = track->x + 0.5f * DXDS( track ) ;
- track->center[1] = track->y + 0.5f * DYDS( track ) ;
- track->center[2] = 0.0f ;
-
- track->cullDetail = trackDetail( radius ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Create a N lane piece of merge in track.
- *----------------------------------------------------------------------------*/
- Track *
- createMergeInTrack(
- int nLanes,
- float length
- )
- {
- int i ;
- float r ;
- Track *track ;
-
- track = myMalloc( sizeof( Track ) ) ;
-
- track->lanes = nLanes ;
- track->type = MERGE_IN_TRACK ;
- track->x = 0.0f ;
- track->y = 0.0f ;
- track->theta = 0.0f ;
- track->length = myMalloc( nLanes * sizeof( float ) ) ;
- for( i = 0 ; i < nLanes ; i++ )
- {
- track->length[i] = length ;
- }
- track->midLane = 1.0f + 0.5f * ( nLanes - 1 ) ;
- track->follow = followTheMergeTrack ;
- track->add = addToMergeTrack ;
- track->added = addedMergeInTrack ;
- track->topSpeed = topSpeedMergeTrack ;
- track->nextTrack = NULL ;
- track->drawList = glGenLists( MAX_LOD ) ;
- track->drawMarkerList = glGenLists( MAX_LOD ) ;
- track->startPosition = NULL ;
- track->endPosition = NULL ;
- track->drawOutline = drawMergeOutline ;
- track->trackLength = getTrackLength ;
- track->enter = enterTrack ;
- track->free = freeMergeTrack ;
- track->cullDetail = NULL ;
- track->laneWidth = mergeLaneWidth ;
-
- return( track ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Create a N lane piece of merge out track.
- *----------------------------------------------------------------------------*/
- Track *
- createMergeOutTrack(
- int nLanes,
- float length
- )
- {
- int i ;
- float r ;
- Track *track ;
-
- track = myMalloc( sizeof( Track ) ) ;
-
- track->lanes = nLanes ;
- track->type = MERGE_OUT_TRACK ;
- track->x = 0.0f ;
- track->y = 0.0f ;
- track->theta = 0.0f ;
- track->length = myMalloc( nLanes * sizeof( float ) ) ;
- for( i = 0 ; i < nLanes ; i++ )
- {
- track->length[i] = length ;
- }
- track->midLane = 1.0f + 0.5f * ( nLanes - 1 ) ;
- track->follow = followTheMergeTrack ;
- track->add = addToMergeTrack ;
- track->added = addedMergeOutTrack ;
- track->topSpeed = topSpeedMergeTrack ;
- track->nextTrack = NULL ;
- track->drawList = glGenLists( MAX_LOD ) ;
- track->drawMarkerList = glGenLists( MAX_LOD ) ;
- track->startPosition = NULL ;
- track->endPosition = NULL ;
- track->drawOutline = drawMergeOutline ;
- track->trackLength = getTrackLength ;
- track->enter = enterMergeOutTrack ;
- track->free = freeMergeTrack ;
- track->cullDetail = NULL ;
- track->laneWidth = mergeLaneWidth ;
-
- return( track ) ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Add to a piece of curved track.
- *----------------------------------------------------------------------------*/
- static void
- addToMergeTrack(
- Track *old,
- Track *new
- )
- {
- new->theta = old->theta ;
- new->x = old->x + DXDS( old ) ;
- new->y = old->y + DYDS( old ) ;
- old->nextTrack = new ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Draw the merge in track piece.
- *----------------------------------------------------------------------------*/
- static void
- drawMergeTrack(
- Track *track,
- int lod
- )
- {
- int i ;
- int n ;
- int l ;
- GLfloat w ;
- GLfloat t ;
- GLfloat c ;
- GLfloat s ;
- GLfloat ri ;
- GLfloat ro ;
- GLfloat v[4][2] ;
-
- /*
- * Draw straight pieces first.
- */
- c = cosf( track->theta ) ;
- s = sinf( track->theta ) ;
-
- v[0][1] = 0.0f ;
- v[1][1] = 0.0f ;
- v[2][1] = track->length[1] ;
- v[3][1] = track->length[1] ;
-
- for( l = 1 ; l < track->lanes - 1 ; l++ )
- {
- w = ( (float)l - 0.5f * ( track->lanes - 1 ) ) * LANE_WIDTH ;
- v[0][0] = w - 0.5f * RAIL_WIDTH ;
- v[1][0] = w + 0.5f * RAIL_WIDTH ;
- v[2][0] = w - 0.5f * RAIL_WIDTH ;
- v[3][0] = w + 0.5f * RAIL_WIDTH ;
- glBegin( GL_TRIANGLE_STRIP ) ;
- for( i = 0 ; i < 4 ; i++ )
- {
- glVertex2f( track->x + v[i][0] * c - v[i][1] * s,
- track->y + v[i][0] * s + v[i][1] * c ) ;
- }
- glEnd() ;
- }
-
- n = 16 - lod * 4 ;
- if( n < 4 )
- {
- n = 4 ;
- }
-
- /*
- * Draw left side.
- */
- glBegin( GL_TRIANGLE_STRIP ) ;
- for( i = 0 ; i < n ; i++ )
- {
- t = ( (float)i / (float)( n-1 ) ) ;
- if( t < 0.5f )
- {
- ri = R_LEFT_BEG( track ) + 0.5f * RAIL_WIDTH ;
- ro = ri - RAIL_WIDTH ;
- t = track->theta + t * DTHETA_DS_LEFT_BEG( track ) ;
- c = cosf( t ) ;
- s = sinf( t ) ;
- glVertex2f( CX_LEFT_BEG( track ) + ro * c,
- CY_LEFT_BEG( track ) + ro * s ) ;
- glVertex2f( CX_LEFT_BEG( track ) + ri * c,
- CY_LEFT_BEG( track ) + ri * s ) ;
- }
- else
- {
- ri = R_LEFT_END( track ) + 0.5f * RAIL_WIDTH ;
- ro = ri - RAIL_WIDTH ;
- t = track->theta +
- ( t - 1.0f ) * DTHETA_DS_LEFT_END( track ) ;
- c = cosf( t ) ;
- s = sinf( t ) ;
- glVertex2f( CX_LEFT_END( track ) + ro * c,
- CY_LEFT_END( track ) + ro * s ) ;
- glVertex2f( CX_LEFT_END( track ) + ri * c,
- CY_LEFT_END( track ) + ri * s ) ;
- }
- }
- glEnd() ;
- /*
- * Draw right side.
- */
- glBegin( GL_TRIANGLE_STRIP ) ;
- for( i = 0 ; i < n ; i++ )
- {
- t = ( (float)i / (float)( n-1 ) ) ;
- if( t < 0.5f )
- {
- ri = R_RIGHT_BEG( track ) + 0.5f * RAIL_WIDTH ;
- ro = ri - RAIL_WIDTH ;
- t = track->theta + t * DTHETA_DS_RIGHT_BEG( track ) ;
- c = cosf( t ) ;
- s = sinf( t ) ;
- glVertex2f( CX_RIGHT_BEG( track ) + ro * c,
- CY_RIGHT_BEG( track ) + ro * s ) ;
- glVertex2f( CX_RIGHT_BEG( track ) + ri * c,
- CY_RIGHT_BEG( track ) + ri * s ) ;
- }
- else
- {
- ri = R_RIGHT_END( track ) + 0.5f * RAIL_WIDTH ;
- ro = ri - RAIL_WIDTH ;
- t = track->theta +
- ( t - 1.0f ) * DTHETA_DS_RIGHT_END( track ) ;
- c = cosf( t ) ;
- s = sinf( t ) ;
- glVertex2f( CX_RIGHT_END( track ) + ro * c,
- CY_RIGHT_END( track ) + ro * s ) ;
- glVertex2f( CX_RIGHT_END( track ) + ri * c,
- CY_RIGHT_END( track ) + ri * s ) ;
- }
- }
- glEnd() ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Draw the left curved track markers.
- *----------------------------------------------------------------------------*/
- static void
- drawMergeTrackMarkers(
- Track *track,
- int lod
- )
- {
- int i ;
- int l ;
- int m ;
- int n ;
- int mask ;
- GLfloat w ;
- GLfloat t ;
- GLfloat c ;
- GLfloat s ;
- GLfloat ri ;
- GLfloat dri ;
- GLfloat ro ;
- GLfloat v[4][2] ;
-
- if( lod == MAX_LOD - 1 )
- {
- return ;
- }
-
- n = (int)( ABSFUNC( R_LEFT_BEG( track ) * DTHETA_DS_LEFT_BEG( track ) )
- / SIDE_MARKER_LENGTH );
- n += ( 4 - ( n % 4 ) ) % 4 ;
- m = LEFT_SIDE ;
- dri = -0.5f * LANE_WIDTH ;
- for( l = 0 ; l < 2 ; l++ )
- {
- glBegin( GL_QUADS ) ;
- for( i = 0 ; i < n ; i++ )
- {
- if( ( i % 4 ) == 0 )
- {
- glColor3f( 0.5f, 0.0f, 0.0f ) ;
- }
- else if( ( i % 2 ) == 0 )
- {
- glColor3f( 0.9f, 0.9f, 0.9f ) ;
- }
- t = ( (float)i / (float)( n ) ) ;
- if( t < 0.5f )
- {
- mask = m | BEGINNING ;
- t = track->theta +
- t * track->c[DT_PART|mask] ;
- }
- else
- {
- mask = m | ENDING ;
- t = track->theta +
- ( t - 1.0f ) * track->c[DT_PART|mask] ;
- }
- ri = track->c[R_PART|mask] + dri ;
- ro = ri - SIDE_MARKER_WIDTH ;
- c = cosf( t ) ;
- s = sinf( t ) ;
- if( i % 2 )
- {
- glVertex2f( track->c[CX_PART|mask] + ri * c,
- track->c[CY_PART|mask] + ri * s ) ;
- glVertex2f( track->c[CX_PART|mask] + ro * c,
- track->c[CY_PART|mask] + ro * s ) ;
- }
- else
- {
- glVertex2f( track->c[CX_PART|mask] + ro * c,
- track->c[CY_PART|mask] + ro * s ) ;
- glVertex2f( track->c[CX_PART|mask] + ri * c,
- track->c[CY_PART|mask] + ri * s ) ;
- }
- }
- glEnd() ;
- m = RIGHT_SIDE ;
- dri = 0.5f * LANE_WIDTH + SIDE_MARKER_WIDTH ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Draw the merge in track piece outline.
- *----------------------------------------------------------------------------*/
- static void
- drawMergeOutline(
- Track *track,
- int side
- )
- {
- int i ;
- int n = 5 ;
- int sideMask ;
- int mask ;
- GLfloat r ;
- GLfloat dr ;
- GLfloat t ;
- GLfloat c ;
- GLfloat cx ;
- GLfloat cy ;
- GLfloat s ;
- GLfloat a[2] ;
-
- if( side == TRACK_LEFT_SIDE )
- {
- dr = -0.5f * LANE_WIDTH ;
- }
- else
- {
- dr = 0.5f * LANE_WIDTH ;
- }
-
- sideMask = ( side == TRACK_LEFT_SIDE ) ? LEFT_SIDE : RIGHT_SIDE ;
- for( i = 0 ; i < n ; i++ )
- {
- t = ( (float)i / (float)( n - 1 ) ) ;
- if( t <= 0.5f )
- {
- mask = sideMask | BEGINNING ;
- }
- else
- {
- mask = sideMask | ENDING ;
- t = t - 1.0f ;
- }
- t = track->theta + t * track->c[DT_PART|mask] ;
- r = track->c[R_PART|mask] + dr ;
- c = cosf( t ) ;
- s = sinf( t ) ;
- a[0] = track->c[CX_PART|mask] + r * c ;
- a[1] = track->c[CY_PART|mask] + r * s ;
- glVertex2fv( a ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Return the top speed of a left curved track.
- *----------------------------------------------------------------------------*/
- static float
- topSpeedMergeTrack(
- Track *track,
- float s,
- float l
- )
- {
- float radius ;
-
- if( l < 2.0f || l > (float)( track->lanes + 1 ) )
- {
- return( maxSpeed( ABSFUNC( R_LEFT_BEG( track ) ) ) ) ;
- }
- else
- {
- return( 1.5f * TOP_SPEED ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Free up memory used by a piece of track.
- *----------------------------------------------------------------------------*/
- static void
- freeMergeTrack(
- Track *track
- )
- {
- if( track )
- {
- free( track->length ) ;
- free( track ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Return the length of track at the given lane.
- *----------------------------------------------------------------------------*/
- static float
- getTrackLength(
- Track *track,
- float lane
- )
- {
- float f ;
- int n ;
-
- if( lane < 2.0f )
- {
- f = lane - 1.0f ;
- return( track->length[0] + f *
- ( track->length[1] - track->length[0] ) ) ;
- }
- else if( lane > (float)( track->lanes - 1 ) )
- {
- n = track->lanes - 1 ;
- f = track->lanes - lane ;
- return( track->length[n] + f *
- ( track->length[n-1] - track->length[n] ) ) ;
- }
- else
- {
- return( track->length[1] ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Return the x and y coordinate given the lane and s.
- *----------------------------------------------------------------------------*/
- static void
- getLocation(
- Track *track,
- float s,
- float lane,
- float *x,
- float *y,
- float *theta,
- float *radius
- )
- {
- int mask ;
- float st ;
- float xs ;
- float ys ;
- float cx ;
- float cy ;
- float r ;
- float t ;
- float dt ;
-
- /*
- * Determine if in straight lane.
- */
- if( lane >= 2.0f && lane <= (float)( track->lanes - 1 ) )
- {
- *x = track->x + s * DXDS( track ) +
- ( lane - track->midLane ) * DXDL( track ) ;
- *y = track->y + s * DYDS( track ) +
- ( lane - track->midLane ) * DYDL( track ) ;
- *theta = track->theta ;
- *radius = 1e20 ;
- return ;
- }
- /*
- * Located on first part of curved part of track.
- */
- else
- {
- if( s <= 0.5f )
- {
- mask = BEGINNING ;
- st = s ;
- }
- else
- {
- mask = ENDING ;
- st = s - 1.0f ;
- }
- if( lane < 2.0f )
- {
- mask |= LEFT_SIDE ;
- dt = 2.0f - lane ;
- }
- else
- {
- mask |= RIGHT_SIDE ;
- dt = lane - (float)track->lanes + 1.0f ;
- }
- }
- r = track->c[R_PART | mask] ;
- cx = track->c[CX_PART | mask] ;
- cy = track->c[CY_PART | mask] ;
- t = st * track->c[DT_PART | mask] ;
-
- *theta = dt * t + track->theta ;
- t += track->theta ;
- *x = cx + r * cosf( t ) ;
- *y = cy + r * sinf( t ) ;
- *radius = r ;
-
- if( dt < 1.0f )
- {
- dt = 1.0f - dt ;
- if( lane < 2.0f )
- {
- lane = 2.0f ;
- }
- else
- {
- lane = (float)( track->lanes - 1 ) ;
- }
- *x += dt * ( track->x + s * DXDS( track ) +
- ( lane - track->midLane ) * DXDL( track ) - *x ) ;
- *y += dt * ( track->y + s * DYDS( track ) +
- ( lane - track->midLane ) * DYDL( track ) - *y ) ;
- }
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Correct lanes when entering a merge-out track segment.
- *----------------------------------------------------------------------------*/
- static void
- enterMergeOutTrack(
- Track *track,
- Car *car
- )
- {
- car->lane += 1.0f ;
- }
-
-
-
- /*------------------------------------------------------------------------------
- * Return the location of a point on the track.
- *----------------------------------------------------------------------------*/
- static float
- mergeLaneWidth(
- Track *track,
- float s,
- float lane1,
- float lane2
- )
- {
- float x1 ;
- float y1 ;
- float t1 ;
- float r1 ;
- float x2 ;
- float y2 ;
- float t2 ;
- float r2 ;
-
- if( lane1 < 1.0f )
- {
- lane1 = 1.0f ;
- }
- else if( lane1 > (float)track->lanes )
- {
- lane1 = (float)track->lanes ;
- }
- if( lane2 < 1.0f )
- {
- lane2 = 1.0f ;
- }
- else if( lane2 > (float)track->lanes )
- {
- lane2 = (float)track->lanes ;
- }
-
- getLocation( track, s, lane1, &x1, &y1, &t1, &r1 ) ;
- getLocation( track, s, lane2, &x2, &y2, &t2, &r2 ) ;
-
- x1 = x1 - x2 ;
- y1 = y1 - y2 ;
- return( sqrtf( x1*x1 + y1*y1 ) ) ;
- }
-